{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "lang": "en",
    "tags": [
     "parameters"
    ]
   },
   "outputs": [],
   "source": [
    "epochs = 10"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "lang": "hi"
   },
   "source": [
    "# भाग 6 - CNN का उपयोग करके MNIST पर फेडरेटेड लर्निंग\n",
    "\n",
    "## PyTorch + PySyft की 10 लाइनों में फेडरेटेड लर्निंग में अपग्रेड करें\n",
    "\n",
    "\n",
    "### प्रसंग\n",
    "\n",
    "फेडरेटेड लर्निंग एक बहुत ही रोमांचक और उथल-पुथल करने वाली मशीन लर्निंग तकनीक है जिसका उद्देश्य ऐसी प्रणालियों का निर्माण करना है जो विकेंद्रीकृत डेटा पर सीखते हैं। यह विचार है कि डेटा अपने निर्माता के हाथों में रहता है (जिसे _कार्यकर्ता_ अर्थात _worker_के रूप में भी जाना जाता है), जो गोपनीयता और स्वामित्व में सुधार करने में मदद करता है, और मॉडल श्रमिकों के बीच साझा किया जाता है। एक तत्काल आवेदन उदाहरण के लिए है जब आप पाठ लिखते हैं तो अपने मोबाइल फोन पर अगले शब्द की पूर्वानुमान करते हैं: आप प्रशिक्षण के लिए उपयोग किए जाने वाले डेटा नहीं चाहते हैं - अर्थात आपके पाठ संदेश - एक केंद्रीय सर्वर पर भेजे जाने के लिए।\n",
    "\n",
    "फेडरेटेड लर्निंग का उदय इसलिए डेटा गोपनीयता जागरूकता के प्रसार से कसकर जुड़ा हुआ है, और यूरोपीय संघ में GDPR जो मई 2018 से डेटा संरक्षण को लागू करता है, ने उत्प्रेरक के रूप में काम किया है। विनियमन पर अनुमान लगाने के लिए, Apple या Google जैसे बड़े अभिनेताओं ने इस तकनीक में बड़े पैमाने पर निवेश करना शुरू कर दिया है, खासकर मोबाइल उपयोगकर्ताओं की गोपनीयता की रक्षा करने के लिए, लेकिन उन्होंने अपने उपकरण उपलब्ध नहीं कराए हैं। OpenMined में, हमारा मानना है कि मशीन लर्निंग परियोजना को संचालित करने का इच्छुक व्यक्ति बहुत कम प्रयासों के साथ गोपनीयता संरक्षण उपकरण लागू करने में सक्षम होना चाहिए। हमने एक एकल पंक्ति में डेटा एन्क्रिप्ट करने के लिए उपकरण बनाए हैं [जैसा कि हमारे ब्लॉग पोस्ट में बताया गया है](https://blog.openmined.org/training-cnns-use-spdz/) और अब हम अपने फेडरेटेड लर्निंग फ्रेमवर्क को जारी करते हैं: नया PyTorch 1.0 संस्करण सुरक्षित और स्केलेबल मॉडल के निर्माण के लिए एक सहज ज्ञान युक्त इंटरफ़ेस प्रदान करता है।\n",
    "\n",
    "इस ट्यूटोरियल में, हम सीधे [Pytorch का उपयोग करते हुए MNIST पर CNN को प्रशिक्षित करने का कैनोनिकल उदाहरण](https://github.com/pytorch/examples/blob/master/mnist/main.py) का उपयोग करेंगे और यह बताएंगे कि यह कितना सरल है। हमारे [PySyft लाइब्रेरी](https://github.com/OpenMined/PySyft/) का उपयोग करके फेडरेटेड लर्निंग को इसके साथ लागू करना है। हम उदाहरण के प्रत्येक भाग से गुजरेंगे और उस कोड को रेखांकित करेंगे जो बदल गया है।\n",
    "\n",
    "आप इस सामग्री को [हमारे ब्लॉगपोस्ट](https://blog.openmined.org/upgrad-to-federated-learning-in-10-lines) में भी पा सकते हैं।\n",
    "\n",
    "लेखक:\n",
    "- Théo Ryffel - GitHub: [@LaRiffle](https://github.com/LaRiffle)\n",
    "\n",
    "अनुवादक - nbTranslate\n",
    "\n",
    "संपादक - Urvashi Raheja - Github: [@raheja](https://github.com/raheja)\n",
    "\n",
    "\n",
    "**ठीक है, चलो शुरू करें!**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "lang": "hi"
   },
   "source": [
    "### आयात और मॉडल विनिर्देशों\n",
    "\n",
    "पहले हम आधिकारिक आयात करते हैं"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "from torchvision import datasets, transforms"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "lang": "hi"
   },
   "source": [
    "और PySyft के लिए उन विशिष्ट की तुलना में। विशेष रूप से हम दूरस्थ श्रमिकों को `एलीस` (`alice`) और` बॉब` (`bob`) को परिभाषित करते हैं।"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import syft as sy  # <-- NEW: import the Pysyft library\n",
    "hook = sy.TorchHook(torch)  # <-- NEW: hook PyTorch ie add extra functionalities to support Federated Learning\n",
    "bob = sy.VirtualWorker(hook, id=\"bob\")  # <-- NEW: define remote worker bob\n",
    "alice = sy.VirtualWorker(hook, id=\"alice\")  # <-- NEW: and alice"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "हम सीखने के कार्य की सेटिंग को परिभाषित करते हैं"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Arguments():\n",
    "    def __init__(self):\n",
    "        self.batch_size = 64\n",
    "        self.test_batch_size = 1000\n",
    "        self.epochs = epochs\n",
    "        self.lr = 0.01\n",
    "        self.momentum = 0.5\n",
    "        self.no_cuda = False\n",
    "        self.seed = 1\n",
    "        self.log_interval = 30\n",
    "        self.save_model = False\n",
    "\n",
    "args = Arguments()\n",
    "\n",
    "use_cuda = not args.no_cuda and torch.cuda.is_available()\n",
    "\n",
    "torch.manual_seed(args.seed)\n",
    "\n",
    "device = torch.device(\"cuda\" if use_cuda else \"cpu\")\n",
    "\n",
    "kwargs = {'num_workers': 1, 'pin_memory': True} if use_cuda else {}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### श्रमिकों (Workers) को डेटा लोड करना और भेजना\n",
    "हम पहले डेटा लोड करते हैं और प्रशिक्षण डेटासेट को एक फेडरेटेड डेटासेट में विभाजित करके ` .federate` विधि का उपयोग करते हुए श्रमिकों में विभाजित करते हैं। यह फ़ेडरेटेड डेटासेट अब Federated DataLoader को दिया जाता है। परीक्षण डेटासेट अपरिवर्तित रहता है।"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "federated_train_loader = sy.FederatedDataLoader( # <-- this is now a FederatedDataLoader \n",
    "    datasets.MNIST('../data', train=True, download=True,\n",
    "                   transform=transforms.Compose([\n",
    "                       transforms.ToTensor(),\n",
    "                       transforms.Normalize((0.1307,), (0.3081,))\n",
    "                   ]))\n",
    "    .federate((bob, alice)), # <-- NEW: we distribute the dataset across all the workers, it's now a FederatedDataset\n",
    "    batch_size=args.batch_size, shuffle=True, **kwargs)\n",
    "\n",
    "test_loader = torch.utils.data.DataLoader(\n",
    "    datasets.MNIST('../data', train=False, transform=transforms.Compose([\n",
    "                       transforms.ToTensor(),\n",
    "                       transforms.Normalize((0.1307,), (0.3081,))\n",
    "                   ])),\n",
    "    batch_size=args.test_batch_size, shuffle=True, **kwargs)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "lang": "hi"
   },
   "source": [
    "### सीएनएन (CNN) विनिर्देश\n",
    "यहां हम ठीक उसी सीएनएन का उपयोग करते हैं जो आधिकारिक उदाहरण में।"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Net(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(Net, self).__init__()\n",
    "        self.conv1 = nn.Conv2d(1, 20, 5, 1)\n",
    "        self.conv2 = nn.Conv2d(20, 50, 5, 1)\n",
    "        self.fc1 = nn.Linear(4*4*50, 500)\n",
    "        self.fc2 = nn.Linear(500, 10)\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = F.relu(self.conv1(x))\n",
    "        x = F.max_pool2d(x, 2, 2)\n",
    "        x = F.relu(self.conv2(x))\n",
    "        x = F.max_pool2d(x, 2, 2)\n",
    "        x = x.view(-1, 4*4*50)\n",
    "        x = F.relu(self.fc1(x))\n",
    "        x = self.fc2(x)\n",
    "        return F.log_softmax(x, dim=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### ट्रेन और परीक्षण कार्यों को परिभाषित करें\n",
    "ट्रेन फ़ंक्शन के लिए, क्योंकि डेटा बैचों को `alice` और `bob` में वितरित किया जाता है, आपको प्रत्येक बैच के लिए मॉडल को सही स्थान पर भेजने की आवश्यकता है। फिर, आप सभी ऑपरेशनों को उसी सिंटैक्स के साथ दूरस्थ रूप से करते हैं जैसे आप लोकल Pytorch कर रहे हैं। जब आप काम पूरा कर लेते हैं, तो आपको अपडेट किए गए मॉडल और सुधार देखने के लिए नुकसान (loss) वापस मिल जाता है होता है।"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train(args, model, device, federated_train_loader, optimizer, epoch):\n",
    "    model.train()\n",
    "    for batch_idx, (data, target) in enumerate(federated_train_loader): # <-- now it is a distributed dataset\n",
    "        model.send(data.location) # <-- NEW: send the model to the right location\n",
    "        data, target = data.to(device), target.to(device)\n",
    "        optimizer.zero_grad()\n",
    "        output = model(data)\n",
    "        loss = F.nll_loss(output, target)\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "        model.get() # <-- NEW: get the model back\n",
    "        if batch_idx % args.log_interval == 0:\n",
    "            loss = loss.get() # <-- NEW: get the loss back\n",
    "            print('Train Epoch: {} [{}/{} ({:.0f}%)]\\tLoss: {:.6f}'.format(\n",
    "                epoch, batch_idx * args.batch_size, len(federated_train_loader) * args.batch_size,\n",
    "                100. * batch_idx / len(federated_train_loader), loss.item()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "lang": "hi"
   },
   "source": [
    "परीक्षण फ़ंक्शन नहीं बदलता है!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def test(args, model, device, test_loader):\n",
    "    model.eval()\n",
    "    test_loss = 0\n",
    "    correct = 0\n",
    "    with torch.no_grad():\n",
    "        for data, target in test_loader:\n",
    "            data, target = data.to(device), target.to(device)\n",
    "            output = model(data)\n",
    "            test_loss += F.nll_loss(output, target, reduction='sum').item() # sum up batch loss\n",
    "            pred = output.argmax(1, keepdim=True) # get the index of the max log-probability \n",
    "            correct += pred.eq(target.view_as(pred)).sum().item()\n",
    "\n",
    "    test_loss /= len(test_loader.dataset)\n",
    "\n",
    "    print('\\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\\n'.format(\n",
    "        test_loss, correct, len(test_loader.dataset),\n",
    "        100. * correct / len(test_loader.dataset)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "lang": "hi"
   },
   "source": [
    "### प्रशिक्षण शुरू करो!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "model = Net().to(device)\n",
    "optimizer = optim.SGD(model.parameters(), lr=args.lr) # TODO momentum is not supported at the moment\n",
    "\n",
    "for epoch in range(1, args.epochs + 1):\n",
    "    train(args, model, device, federated_train_loader, optimizer, epoch)\n",
    "    test(args, model, device, test_loader)\n",
    "\n",
    "if (args.save_model):\n",
    "    torch.save(model.state_dict(), \"mnist_cnn.pt\")\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Et voilà! आप यहां पहुंच गए हैं, आपने फेडरेटेड लर्निंग का उपयोग करके दूरस्थ डेटा पर एक मॉडल को प्रशिक्षित किया है!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## एक अंतिम बात\n",
    "मुझे पता है कि एक सवाल है जो आप पूछना चाहते हैं: **सामान्य Pytorch की तुलना में फेडरेटेड लर्निंग को करने में कितना समय लगता है?**\n",
    "\n",
    "वास्तव में गणना समय का उपयोग **सामान्य PyTorch निष्पादन के समय के दो बार से कम समय में** किया जाता है! अधिक सटीक रूप से, इसमें 1.9 गुना अधिक समय लगता है, जो उन विशेषताओं की तुलना में बहुत कम है जिन्हें हम जोड़ने में सक्षम थे।"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "lang": "hi"
   },
   "source": [
    "## निष्कर्ष\n",
    "\n",
    "जैसा कि आप निरीक्षण करते हैं, हमने MNIST पर आधिकारिक Pytorch उदाहरण को वास्तविक फेडरेटेड लर्निंग सेटिंग में अपग्रेड करने के लिए कोड की 10 लाइनों को संशोधित किया है!\n",
    "\n",
    "बेशक, ऐसे दर्जनों सुधार हैं जिनके बारे में हम सोच सकते थे। हम कामगारों के समानांतर काम करना चाहते हैं और फेडरेटेड एवरेज का प्रदर्शन करना चाहते हैं, केंद्रीय मॉडल को अपडेट करने के लिए हर `n` बैचों को केवल श्रमिकों के बीच संचार के लिए हमारे द्वारा उपयोग किए जाने वाले संदेशों की संख्या को कम करने के लिए, आदि ये हम हैं ' फेडरेटेड लर्निंग को प्रोडक्शन के माहौल के लिए तैयार करने के लिए काम कर रहे हैं और रिलीज़ होते ही हम उनके बारे में लिखेंगे!\n",
    "\n",
    "अब आपको फेडरेटेड लर्निंग को खुद से करने में सक्षम होना चाहिए! यदि आपने इसका आनंद लिया और एआई और एआई आपूर्ति श्रृंखला (डेटा) के विकेन्द्रीकृत स्वामित्व के संरक्षण, गोपनीयता की ओर आंदोलन में शामिल होना चाहते हैं, तो आप निम्न तरीकों से ऐसा कर सकते हैं!\n",
    "\n",
    "### GitHub पर स्टार PySyft\n",
    "\n",
    "हमारे समुदाय की मदद करने का सबसे आसान तरीका सिर्फ रिपॉजिटरी को अभिनीत करना है! यह हमारे द्वारा बनाए जा रहे कूल टूल्स के बारे में जागरूकता बढ़ाने में मदद करता है।\n",
    "\n",
    "- [अभिनीत PySyft](https://github.com/OpenMined/PySyft)\n",
    "\n",
    "### GitHub पर हमारे ट्यूटोरियल चुनना !\n",
    "\n",
    "हमने फेडरेटेड और प्राइवेसी-प्रिजर्विंग लर्निंग की बेहतर समझ पाने के लिए वास्तव में अच्छा ट्यूटोरियल बनाया और ऐसा होने के लिए हम ईंटों का निर्माण कर रहे हैं।\n",
    "\n",
    "- [PySyft ट्यूटोरियल्स को चेक करें](https://github.com/OpenMined/PySyft/tree/master/examples/tutorials)\n",
    "\n",
    "\n",
    "### हमारे Slack में शामिल हों!\n",
    "\n",
    "नवीनतम प्रगति पर अद्यतित रहने का सबसे अच्छा तरीका हमारे समुदाय में शामिल होना है!\n",
    "\n",
    "- [slack.openmined.org से जुड़ें](http://slack.openmined.org)\n",
    "\n",
    "### एक कोड परियोजना में शामिल हों!\n",
    "\n",
    "हमारे समुदाय में योगदान करने का सबसे अच्छा तरीका एक कोड योगदानकर्ता बनना है! यदि आप \"एक बंद\" मिनी-प्रोजेक्ट्स शुरू करना चाहते हैं, तो आप PySyft GitHub जारी करने वाले पृष्ठ पर जा सकते हैं और 'अच्छा पहला अंक' (Good First Issue Tickets) चिह्नित मुद्दों की खोज कर सकते हैं।\n",
    "\n",
    "- [अच्छा पहला अंक टिकट](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+fueue%22)\n",
    "\n",
    "### दान करना\n",
    "\n",
    "यदि आपके पास हमारे कोडबेस में योगदान करने का समय नहीं है, लेकिन फिर भी समर्थन उधार देना चाहते हैं, तो आप हमारे ओपन कलेक्टिव में भी एक बैकर बन सकते हैं। सभी दान हमारी वेब होस्टिंग और अन्य सामुदायिक खर्चों जैसे कि हैकाथॉन और मीटअप की ओर जाते हैं!\n",
    "\n",
    "- [OpenMined's Open कलेक्टिव पेज के माध्यम से दान करें](https://opencollective.com/openmined)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "celltoolbar": "Tags",
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  },
  "nbTranslate": {
   "displayLangs": [
    "hi"
   ],
   "hotkey": "alt-t",
   "langInMainMenu": true,
   "sourceLang": "en",
   "targetLang": "hi",
   "useGoogleTranslate": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
